namespace GYLite
{
	export class GYGroup extends GYUIComponent
	{
		protected _scrollPadLeft:number;
		protected _scrollPadRight:number;
		protected _scrollPadTop:number;
		protected _scrollPadBottom:number;
		
		protected _clipAndEnableScrolling:boolean;
		protected _clipRect:egret.Rectangle;
		public $clipX:number;
		public $clipY:number;
		protected _canDrag:boolean;
		protected _verticalDrag:boolean;
		protected _horizonDrag:boolean;
		protected _scroller:GYScroller;
		protected _easeGapY:boolean;
		protected _easeGapX:boolean;
		protected _easeXFix:number;
		protected _easeYFix:number;		
		protected _easeSpeedValue:number;
		protected _clipChange:boolean;
		protected _tweenX:GYTween;
		protected _tweenY:GYTween;	
		protected _touchId:number;	
		/**产生缓动的速度*/public easeValue:number;
		// /**回弹系数（乘以速度）*/protected _easeBackValue:number=NaN;
		/**拖动敏感度*/public dragValue:number;
		/**边界拖拽系数*/protected _dragEaseValue:number;
		/**拖拽步长最大值*/protected _dragEaseMax:number;
		/**缓动越界最大值*/protected _easeMoveMax:number;
		/**触发缓动的时间阈值*/protected _easeTriggerTime:number;
		/**弹性恢复时间*/protected _easeTime:number;
		protected _innerSprite:InnerSprite;
		protected _endPointer:GYSprite;
		protected _outSideSp:InnerSprite;
		protected _indexArray:Array<IGYDisplay>;
		protected _outSideOptimize:boolean;
		protected _lastXDragTime:number;		
		protected _lastYDragTime:number;
		protected _moveXTime:number;
		protected _moveYTime:number;
		protected _scrollSpeedX:number;	
		protected _scrollSpeedY:number;	
		protected _limitXMin:number;
		protected _limitXMax:number;
		protected _limitYMin:number;
		protected _limitYMax:number;
		protected _isDragging:boolean;
		/**是否拖拽时禁止滚轮，默认true*/public dragForbiddenWheel:boolean;
		public constructor()
		{
			super();
			var s = this;			
			s.$clipX = 0;
			s.$clipY = 0;
			s._easeXFix = 0;
			s._easeYFix = 0;
			s._verticalDrag = true;
			s._horizonDrag = true;
			s._disabledZIndex = false;
			s._touchId = NaN;
			s._scrollPadLeft = 0;
			s._scrollPadRight = 0;
			s._scrollPadTop = 0;
			s._scrollPadBottom = 0;
			s._limitXMin = 0;
			s._limitYMin = 0;
			s._limitXMax = NaN;
			s._limitYMax = NaN;
			s.easeValue = GYGroup.default_easeValue;
			// s._easeBackValue = GYGroup.default_easeBackValue;
			s.dragValue = GYGroup.default_dragValue;
			s._dragEaseValue = GYGroup.default_dragEaseValue;
			s._dragEaseMax = GYGroup.default_dragEaseMax;
			s._easeMoveMax = GYGroup.default_easeMoveMax;
			s._easeSpeedValue = GYGroup.default_easeSpeedValue;
			s._easeTriggerTime = GYGroup.default_easeTriggerTime;
			s._easeTime = GYGroup.default_easeTime;
			s._scrollSpeedX = 1;
			s._scrollSpeedY = 1;
			//层级列表，所有显示对象排序数组，变化时用zindex刷新
			s._indexArray = [];
			//_outSideSp内层容器，装载显示区域外的显示对象
			s._outSideSp = new InnerSprite(s);
			s._outSideSp.disabledZIndex = true;
			s._outSideSp.scrollRect = new egret.Rectangle(0,0,5,5);
			//_innerSprite内层容器，装载显示区域内的显示对象
			s._innerSprite = new InnerSprite(s);
			s._innerSprite.disabledZIndex = true;
			s._innerSprite.touchEnabled = true;
			// s._innerSprite.viewChangeCallParent = true;
			super.addElement(s._innerSprite);
			s._endPointer = new GYSprite;
			s._endPointer.width = 1;
			s._endPointer.height = 1;			
			super.addElement(s._endPointer);//此为宽高标记容器，索引列表里面没有，不能使用_innerSprite添加
			s._outSideOptimize = true;
			s._clipRect = new egret.Rectangle;
			s.dragForbiddenWheel = true;
		}
		/**本容器添加按索引，非内层容器*/
		public baseAddAt(child:IGYDisplay, index:number):void
		{
			super.addElementAt(child, index);
		}
		/**本容器添加，非内层容器*/
		public baseAdd(child:IGYDisplay):void
		{
			super.addElement(child);
		}
		/**本容器添加，非内层容器*/
		public baseRemove(child:IGYDisplay):void
		{let s = this;
			super.removeElement(child);
		}
		/**@inheritDoc */
		public getElementAt(index:number):IGYDisplay
		{let s = this;
			return s._indexArray[index];
		}
		/**@inheritDoc */
		public getElementIndex(child:IGYDisplay):number
		{
			let s = this;
			let ind:number = s._indexArray.indexOf(child);
			return ind;
		}
		/**@inheritDoc*/
		public delElement(child:IGYDisplay):void
		{
			let s = this;
			if(child.parent == s._innerSprite)
				s._innerSprite.delElement(child);
			else if(child.parent == s._outSideSp)
				s._outSideSp.delElement(child);
			else if(child.parent == s)
				super.delElement(child);			
		}		
		/**@inheritDoc*/
		public addElement(disObj:IGYDisplay):IGYDisplay
		{
			let s = this;
			let ind:number = s._indexArray.indexOf(disObj);
			if(ind > -1)
				s._indexArray.splice(ind,1);
			s._indexArray.push(disObj);
			// if(s._indexArray.length > 10000)
			// 	console.warn("子级数组数量超过2000!请注意是否使用了GYGroup容器，直接用parent进行移除，正确应使用getLayoutContainer()获取parent进行移除!")
			s.invalidZIndex();
			s.invalidDisplay();
			s._innerSprite.addElement(disObj);
			if(s._outSideOptimize)
				s.checkOutSize(disObj,false);//刷新屏外检测，zIndex延时统一刷新
			return disObj;
		}
		/**@inheritDoc*/
		public addElementAt(disObj:IGYDisplay, index:number):IGYDisplay
		{
			let s = this;
			let ind:number = s._indexArray.indexOf(disObj);
			if(ind > -1)
				s._indexArray.splice(ind,1);
			s._indexArray.splice(index,0,disObj);
			// if(s._indexArray.length > 10000)
			// 	console.warn("子级数组数量超过2000!请注意是否使用了GYGroup容器，直接用parent进行移除，正确应使用getLayoutContainer()获取parent进行移除!")
			s.invalidZIndex();		
			s.invalidDisplay();	
			s._innerSprite.addElement(disObj);
			if(s._outSideOptimize)
				s.checkOutSize(disObj,false);//刷新屏外检测，zIndex延时统一刷新
			return disObj;
		}
		/**@inheritDoc*/
		public removeElement(disObj:IGYDisplay):IGYDisplay
		{
			let s = this;
			if(disObj.parent == s)//可能添加到了容器了，不在innerSprite
				return super.removeElement(disObj);
			let child:IGYDisplay;
			if(disObj.parent == s._innerSprite)
				child = s._innerSprite.removeElement(disObj);
			else if(disObj.parent == s._outSideSp)
				child = s._outSideSp.removeElement(disObj);
			else
				egret.$error(1006);
			let ind:number = s._indexArray.indexOf(disObj);
			if(ind > -1)
				s._indexArray.splice(ind,1);
			s.invalidZIndex();
			s.invalidDisplay();
			return child;			
		}
		/**@inheritDoc*/
		public removeElementAt(index:number):IGYDisplay
		{
			let s = this;					
			let child:IGYDisplay = s._indexArray[index];
			if(child ==null)
				egret.$error(1007);
			if(child.parent == s._innerSprite)
				s._innerSprite.removeElement(child);
			else if(child.parent == s._outSideSp)
				s._outSideSp.removeElement(child);
			s._indexArray.splice(index,1);
			s.invalidZIndex();
			s.invalidDisplay();
			return child;			
		}
		/**@inheritDoc*/
		public removeAllElement():void
		{
			let s = this;
			s._innerSprite.removeAllElement();
			s._outSideSp.removeAllElement();
		}
		/**@inheritDoc*/
		public setElementIndex(child:IGYDisplay,index:number):void
		{
			let s = this;
			let tempChild:IGYDisplay;		
			if(index >= s._indexArray.length)
				throw(new Error("索引" + index + "超出范围！"));
			let ind:number = s._indexArray.indexOf(child);
			if(ind == -1)
				throw(new Error("无法调整非子级的索引"));			
			tempChild = s._indexArray[index];
			if(tempChild == child)
				return;
			s._indexArray.splice(ind,1);
			// ind = s._indexArray.indexOf(tempChild);
			s._indexArray.splice(index,0,child);
			s.invalidZIndex();
		}
		/**@inheritDoc*/
		public swapElementIndex(child1,child2):void
		{
			let s = this;
			let nextNode;			
			var tempIndex = s._indexArray.indexOf(child1);
			if(tempIndex >= s._indexArray.length)
				throw(new Error("索引" + tempIndex + "超出范围！"));
			var tempIndex2 = s._indexArray.indexOf(child2);
			if(tempIndex2 >= s._indexArray.length)
				throw(new Error("索引" + tempIndex2 + "超出范围！"));
			if(tempIndex == tempIndex2)
				return;
			s._indexArray[tempIndex] = child2;
			s._indexArray[tempIndex2] = child1;
			s.invalidZIndex();
		}		
		public get numElement():number
		{
			let s = this;
			return s._indexArray.length;
		}
		public getElementList():Array<IGYDisplay>
		{
			return this._innerSprite.getElementList();
		}		
		/**@inheritDoc*/
		public updateView():void
		{
			let s = this;
			if(s._clipChange)
			{
				s.validClip();
				s._clipChange = false;
			}
			super.updateView();
		}
		/**刷新裁剪*/
		public invalidClip():void
		{
			let s = this;
			if(s._clipChange)
				return;
			s._clipChange = true;
			s.displayChg();
		}
		public set clipAndEnableScrolling(val:boolean)
		{
			let s = this;
			s._clipAndEnableScrolling = val;
			if(val)
			{
				if(s._canDrag)
				{
					s.addEventListener(egret.TouchEvent.TOUCH_BEGIN, s.downGroup,s);
				}
				if(s.$width != s.$width && s.$height != s.$height)
					return;
				s.invalidClip();
			}
			else
			{
				s.scrollRect.setEmpty();
				s.removeEventListener(egret.TouchEvent.TOUCH_BEGIN, s.downGroup,s);
			}
		}
		/**是否允许裁切边界进行滚动*/
		public get clipAndEnableScrolling():boolean
		{
			let s = this;
			return s._clipAndEnableScrolling;
		}
		public set width(val:number)
		{
			let s = this;			
			// if(s.$width == val)
			// 	return;
			// s.group_width = val;
			s.set_width(val);
		}		
		public get width():number
		{
			return this.get_width();
		}
		public set height(val:number)
		{
			let s = this;	
			// if(s.$height == val)
			// 	return;
			// s.group_height = val;
			s.set_height(val);
		}
		public get height():number
		{
			return this.get_height();
		}
		public set_width(val:number):boolean
		{
			let s = this;
			if(super.set_width(val))
			{
				if(s._clipAndEnableScrolling)
					s.invalidClip();
				return true;
			}
			return false;
		}
		public set_height(val:number):boolean
		{
			let s = this;
			if(super.set_height(val))
			{
				if(s._clipAndEnableScrolling)
					s.invalidClip();
				return true;
			}			
			return false;			
		}
		
		public validClip():void
		{
			var s = this;
			var flag:boolean;			
			flag = (s._clipRect.x != s.$clipX || s._clipRect.y != s.$clipY);
			s._clipRect.x=s.$clipX;
			s._clipRect.y=s.$clipY;			
			if(flag && s.hasEventListener(GYViewEvent.CLIP_SCROLL))
				s.dispatchEvent(new GYViewEvent(GYViewEvent.CLIP_SCROLL));			
			flag = (s._clipRect.width == s.baseWidth && s._clipRect.height == s.baseHeight);
			s._clipRect.width = s.baseWidth;
			s._clipRect.height = s.baseHeight;
			if(s._outSideOptimize)
				s.checkOutSize(null,true);			
			egret.superSetter(GYGroup, s, "scrollRect", s._clipRect);			
			if(!flag)
				s.invalidDisplay();
		}
		/**请使用s.clipAndEnableScrolling以实现*/
		public get scrollRect():egret.Rectangle
		{
			let s = this;
			return s._clipRect;
		}
		public set scrollRect(rect:egret.Rectangle)
		{
			let s = this;
			return;
		}
		public set clipX(val:number)
		{
			let s = this;			
			s.$clipX=val;
			if(s._clipAndEnableScrolling)
				s.invalidClip();
		}
		public set clipY(val:number)
		{
			let s = this;			
			s.$clipY=val;
			if(s._clipAndEnableScrolling)
				s.invalidClip();
		}
		/**s.clipAndEnableScrolling为true时有效，s.scrollRect滚动的s.x坐标*/
		public get clipX():number
		{
			return this.$clipX;
		}
		/**s.clipAndEnableScrolling为true时有效，s.scrollRect滚动的s.y坐标*/
		public get clipY():number
		{
			return this.$clipY;
		}
		public get scroller():GYScroller
		{
			let s = this;
			return s._scroller;
		}
		public set scroller(val:GYScroller)			
		{
			let s = this;
			s._scroller = val;
			if(s._scroller)
			{
				if(s._scroller.verticalPolicy != 2)
				{
					s._scroller.scrollBarV.limitMin = s._limitYMin;
					s._scroller.scrollBarV.limitMax = s._limitYMax;
				}
				if(s._scroller.horizonPolicy != 2)
				{
					s._scroller.scrollBarH.limitMin = s._limitXMin;
					s._scroller.scrollBarH.limitMax = s._limitXMax;
				}				
			}				
		}
		
		/**能否拖动,仅在s.clipAndEnableScrolling为true时有效* */
		public get canDrag():boolean
		{
			let s = this;
			return s._canDrag;
		}
		public set canDrag(val:boolean)
		{
			let s = this;
			if(s._canDrag == val)
				return;
			s._canDrag = val;
			if(s._canDrag && s._clipAndEnableScrolling)
			{
				s.addEventListener(egret.TouchEvent.TOUCH_BEGIN, s.downGroup,s);
			}
			else
			{
				s.removeEventListener(egret.TouchEvent.TOUCH_BEGIN, s.downGroup,s);
			}
		}
		/**是否允许纵向拖动，当s.canDrag为true时才有效*/
		public get verticalDrag():boolean
		{
			let s = this;
			return s._verticalDrag;
		}
		public set verticalDrag(val:boolean)
		{
			let s = this;
			s._verticalDrag = val;
		}
		/**是否允许横向拖动，当s.canDrag为true时才有效*/
		public get horizonDrag():boolean
		{
			let s = this;
			return s._horizonDrag;
		}
		public set horizonDrag(val:boolean)
		{
			let s = this;
			s._horizonDrag = val;
		}
		protected downGroup(e:egret.TouchEvent):void
		{
			let s = this;			
			if(!s._canDrag || !s._clipAndEnableScrolling)return;
			s._touchId = e.touchPointID;
			if(GYSprite.pushGlobalDrag(this))
				s.groupDrag();
			else
				s.addEventListener(GYEvent.GLOABL_DRAG, s.globalDragCall,s);
		}
		protected upGroup(e:egret.TouchEvent=null):void
		{
			let s = this;
			if(e && e.currentTarget != e.target && e.type == GYTouchEvent.RELEASE_OUTSIDE)return;
			s._touchId = NaN;
			s.groupDragStop();
			GYSprite.clearGlobalDrags();
		}
		protected globalDragCall(e:GYEvent):void
		{
			let s = this;
			s.removeEventListener(GYEvent.GLOABL_DRAG, s.globalDragCall,s);
			s.groupDrag();
		}
		protected groupDrag():void
		{
			let s = this;
			if(s._tweenX && s.easeSpeedX != 0 || s._tweenY && s.easeSpeedY != 0)s.dragLock =true;//有缓动并且速度大于0才可以立即锁住
			if(s._tweenX)
			{
				s._tweenX.clear();
				s._tweenX = null;
			}
			if(s._tweenY)
			{
				s._tweenY.clear();
				s._tweenY = null;
			}
			if(s._scroller && s._scroller.horizonPolicy != 2)
			{
				s._scroller.scrollBarH.stopScroll();
			}
			if(s._scroller && s._scroller.horizonPolicy != 1)
			{
				s._scroller.scrollBarV.stopScroll();
			}
			
			s.validClip();//刷新一下clipy
			// CommonUtil.addStageLoop(s.dragLoop,s);
			GYSprite.stage.addEventListener(egret.TouchEvent.TOUCH_MOVE,s.touchMove,s);
			s._lastYDragTime = s._lastXDragTime = Date.now();			
			s.tempY = s.mouseY - s.$clipY;
			s.tempX = s.mouseX - s.$clipX;
			s._moveYTime = s._moveXTime = s.easeSpeedX = s.easeSpeedY =0;
			GYSprite.addStageDown(s, s.upGroup, s);
			s.addEventListener(egret.TouchEvent.TOUCH_END, s.upGroup,s);
		}
		public clearGlobalDrag():void
		{
			let s = this;
			s.removeEventListener(GYEvent.GLOABL_DRAG, s.groupDrag,s);
			s.groupDragStop();
		}
		protected groupDragStop():void
		{
			let s = this;
			s._isDragging = false;
			s.removeEventListener(egret.TouchEvent.TOUCH_END, s.upGroup,s);
			// CommonUtil.delStageLoop(s.dragLoop,s);
			GYSprite.stage.removeEventListener(egret.TouchEvent.TOUCH_MOVE,s.touchMove,s);
			
			let dis:number;
			var flag:boolean;
			var temp:number,tarPos:number,addDis:number;
			let cpX:number,cpY:number;
			let frameParam:number;
			frameParam = 1000/egret.ticker.$frameRate;
			cpX = s.clipX;
			cpY = s.clipY;
			s.dispatchEvent(new GYViewEvent(GYViewEvent.DRAGSTOP));
			dis=s._limitXMax==s._limitXMax?s._limitXMax:s.contentWidth - s.baseWidth;
			if(dis < s._limitXMin)dis = s._limitXMin;
			let nt:number = Date.now();
			let dt:number = s._moveXTime;
			let spd:number;
			let flagA:boolean,flagB:boolean,flagC:boolean;
            flagA = cpX < s._limitXMin && s.easeSpeedX > s.easeValue;//超左边界，向左缓动
            flagB = cpX > dis && s.easeSpeedX < -s.easeValue;//超右边界，向右缓动
            flagC = cpX < dis && cpX > s._limitXMin;//正常缓动
			if(dt > 0 && nt - s._lastXDragTime < s._easeTriggerTime && (flagA || flagB || flagC))
			{
				spd = s.easeSpeedX / dt * frameParam;	
				addDis = Math.abs(spd) * spd * s._easeSpeedValue;
				temp = cpX + addDis;
				if(temp < s._limitXMin)
				{
					tarPos = s.easeGapX?((!flagA && temp < -s._easeMoveMax + s._limitXMin)?-s._easeMoveMax + s._limitXMin:temp):s._limitXMin;
					addDis = tarPos - cpX;
				}						
				else if(temp > dis)
				{
					tarPos = s.easeGapX?((!flagB && temp > dis + s._easeMoveMax)?dis + s._easeMoveMax:temp):dis;
					addDis = tarPos - cpX;
				}
				else
				{
					tarPos = temp;					
				}
					
				let t:number = (temp < s._limitXMin || temp > dis)?s._easeTime:(Math.abs(addDis / spd * frameParam * 2));
				if(s._scroller && s._scroller.horizonPolicy != 2)
				{					
					s._scroller.scrollBarH.scrollToPosition(tarPos, t);
				}					
				else
				{					
					s.clipXEaseTo(tarPos, t);
				}					
			}
			else
			{
				s.easeSpeedX = 0;
				if(s._easeGapX)
				{					
					if(s.clipX < s._limitXMin)
						s.clipXEaseTo(s.clipX < -s.easeXFix+s._limitXMin?-s.easeXFix+s._limitXMin:s._limitXMin, s._easeTime);
					else if(s.clipX > dis)
						s.clipXEaseTo((s.clipX > dis + s.easeXFix)?dis + s.easeXFix:dis, s._easeTime);
				}
			}
			dis=s._limitYMax==s._limitYMax?s._limitYMax:s.contentHeight - s.baseHeight;
			if(dis < s._limitYMin)dis =s._limitYMin;
			dt = s._moveYTime;
			flagA = cpY < s._limitYMin && s.easeSpeedY > s.easeValue;//超左边界，向左缓动
            flagB = cpY > dis && s.easeSpeedY < -s.easeValue;//超右边界，向右缓动
            flagC = cpY < dis && cpY > s._limitYMin;//正常缓动
			if(dt > 0 && nt - s._lastYDragTime < s._easeTriggerTime && (flagA || flagB || flagC))
			{
				spd = s.easeSpeedY / dt * frameParam;			
				addDis = Math.abs(spd) * spd * s._easeSpeedValue;
				temp = cpY + addDis;
				if(temp < s._limitYMin)
				{
					tarPos = s.easeGapY?(temp < -s._easeMoveMax + s._limitYMin?-s._easeMoveMax + s._limitYMin:temp):s._limitYMin;
					addDis = tarPos - cpY;
				}						
				else if(temp > dis)
				{
					tarPos = s.easeGapY?(temp > dis + s._easeMoveMax?dis + s._easeMoveMax:temp):dis;
					addDis = tarPos - cpY;
				}
				else
					tarPos = temp;
				let t:number = (temp < s._limitXMin || temp > dis)?s._easeTime:(Math.abs(addDis / spd * frameParam * 2));
				if(s._scroller && s._scroller.verticalPolicy != 2){					
					s._scroller.scrollBarV.scrollToPosition(tarPos, t);
				}					
				else
				{					
					s.clipYEaseTo(tarPos, t);
				}
					
			}
			else
			{
				s.easeSpeedY = 0;
				if(s._easeGapY)
				{
					if(s.clipY < s._limitYMin)
						s.clipYEaseTo(s.clipY < -s._easeYFix+s._limitYMin?-s._easeYFix+s._limitYMin:s._limitYMin, s._easeTime);
					else if(s.clipY > dis)
						s.clipYEaseTo((s.clipY > dis + s._easeYFix)?dis + s._easeYFix:dis, s._easeTime);
				}
			}			
			s.dragLock=false;
		}		
		protected touchMove(e:egret.TouchEvent):void
		{let s = this;
			if(s._touchId == e.touchPointID)
				s.dragLoop(Date.now());
		}
		protected tempY:number=NaN;
		protected tempX:number=NaN;
		protected easeSpeedX:number=0;
		protected easeSpeedY:number=0;
		protected dragLoop(t:number):void
		{
			let s = this;
			var temp:number,temp2:number;
			var mX:number,mY:number;	
			let xFlag:boolean,yFlag:boolean;
			let tick:number;
			let frameParam:number;
			tick = Date.now();
			frameParam = 1000/egret.ticker.$frameRate|0;
			xFlag = s._moveXTime < 100;
			yFlag = s._moveYTime < 100;
			s._moveXTime = xFlag?s._moveXTime + Math.min(frameParam,tick - s._lastXDragTime):Math.min(frameParam,tick - s._lastXDragTime);
			s._moveYTime = yFlag?s._moveYTime + Math.min(frameParam,tick - s._lastYDragTime):Math.min(frameParam,tick - s._lastYDragTime);
			s._lastYDragTime = s._lastYDragTime = tick;
			if(s._verticalDrag)
			{
				mY = s.mouseY - s._clipRect.y;
				temp = s.tempY - mY;
				if(s._dragLock || Math.abs(temp) > s.dragValue)
				{
					s._isDragging = true;
					s.dragLock=true;						
					s.easeSpeedY = yFlag?s.easeSpeedY + temp:temp;
					var dis:number=s._limitYMax==s._limitYMax?s._limitYMax:s.contentHeight - s.baseHeight;
					if(dis < s._limitYMin)dis =s._limitYMin;
					temp2 = s.clipY + temp;//temp2为变化后的总量，temp为增量，_clipY为当前滚动pos值					
					if(s.easeGapY && temp2 > dis && temp > 0)
					{
						s.dragEnd_Vertical();
						if(GYSprite.shiftGlobalDrag(1))
						{
							s.clipY = dis;
							s.clearGlobalDrag();
						}
						else 
						{
							if(temp > s._dragEaseMax)temp = s._dragEaseMax;
							temp = temp * s._dragEaseValue/(1 + temp2 - dis + s._dragEaseValue);								
							s.clipY += temp;
						}						
					}
					else if(s.easeGapY && temp2 < s._limitYMin && temp < 0)
					{
						s.dragEnd_Vertical();
						if(GYSprite.shiftGlobalDrag(1))
						{
							s.clipY = s._limitYMin;
							s.clearGlobalDrag();
						}
						else 
						{
							if(-temp > s._dragEaseMax)temp = -s._dragEaseMax;
							temp = temp * s._dragEaseValue/(1 - temp2 + s._dragEaseValue);									
							s.clipY += temp;							
						}
					}
					else
					{						
						if(s._scroller && s._scroller.verticalPolicy != 2)
						{
							s._scroller.scrollBarV.position = temp2;
							if(temp2 < s._limitYMin || temp2 < 0)
								s.clipY = temp2;
							else if(temp2 > s._limitYMax || temp2 > s._scroller.scrollBarV.maximum)
								s.clipY = temp2;
						}							
						else
							s.clipY = temp2;						
						if(!s.easeGapY)
						{
							if(s.$clipY > dis)
							{
								if(GYSprite.shiftGlobalDrag(1))
									s.clearGlobalDrag();
								if(!s.easeGapY)
									s.clipY = dis;
								s.dragEnd_Vertical();
							}
							else if(s.$clipY < s._limitYMin)
							{
								if(GYSprite.shiftGlobalDrag(1))
									s.clearGlobalDrag();
								if(!s.easeGapY)
									s.clipY = s._limitYMin;
								s.dragEnd_Vertical();
							}
						}
					}					
					s.tempY = mY;
				}
			}
			if(s._horizonDrag)
			{
				mX = s.mouseX - s._clipRect.x;
				temp = s.tempX - mX;
				if(s._dragLock || Math.abs(temp) > s.dragValue)
				{
					s._isDragging = true;
					s.dragLock=true;					
					s.easeSpeedX = xFlag?s.easeSpeedX + temp:temp;			
					dis=s._limitXMax==s._limitXMax?s._limitXMax:s.contentWidth - s.baseWidth;
					if(dis < s._limitXMin)dis =s._limitXMin;
					temp2 = s.clipX + temp;
					if(s.easeGapX && temp2 > dis && temp > 0)
					{
						s.dragEnd_Horizonal();
						if(GYSprite.shiftGlobalDrag(2))
						{
							s.clipX = dis;
							s.clearGlobalDrag();
						}
						else 
						{
							if(temp > s._dragEaseMax)temp = s._dragEaseMax;
							temp = temp * s._dragEaseValue/(1 + temp2 - dis + s._dragEaseValue);	
							s.clipX += temp;							
						}
					}
					else if(s.easeGapX && temp2 < s._limitXMin && temp < 0)
					{
						s.dragEnd_Horizonal();
						if(GYSprite.shiftGlobalDrag(2))
						{
							s.clipX = s._limitXMin;
							s.clearGlobalDrag();
						}
						else 
						{
							if(-temp > s._dragEaseMax)temp = -s._dragEaseMax;
							temp = temp * s._dragEaseValue/(1 - temp2 + s._dragEaseValue);								
							s.clipX += temp;							
						}
					}
					else
					{
						if(s._scroller && s._scroller.horizonPolicy != 2)
						{
							s._scroller.scrollBarH.position = temp2;
							if(temp2 < s._limitXMin || temp2 < 0)
								s.clipX = temp2;
							else if(temp2 > s._limitXMax || temp2 > s._scroller.scrollBarH.maximum)
								s.clipX = temp2;
						}
						else
							s.clipX = temp2;
						if(!s.easeGapX)
						{
							if(s.$clipX > dis)
							{
								if(GYSprite.shiftGlobalDrag(2))
									s.clearGlobalDrag();
								if(!s.easeGapX)
									s.clipX = dis;
								s.dragEnd_Horizonal();
							}
							else if(s.$clipX < s._limitXMin)
							{
								if(GYSprite.shiftGlobalDrag(2))
									s.clearGlobalDrag();	
								if(!s.easeGapX)
									s.clipX = s._limitXMin;
								s.dragEnd_Horizonal();
							}
						}
					}
					s.tempX = mX;
				}
			}
		}
		private dragEnd_Horizonal():void
		{
			let s = this;
			if(s.hasEventListener(GYViewEvent.DRAGEND_HORIZONAL))
				s.dispatchEvent(new GYViewEvent(GYViewEvent.DRAGEND_HORIZONAL));
		}
		private dragEnd_Vertical():void
		{
			let s = this;
			if(s.hasEventListener(GYViewEvent.DRAGEND_VERTICAL))
				s.dispatchEvent(new GYViewEvent(GYViewEvent.DRAGEND_VERTICAL));
		}
		/**缓动到某Y坐标
		 * @param val 坐标值Y
		 * @param time 缓动时间
		*/
		public clipYEaseTo(val:number,time:number=1000):void
		{
			let s = this;
			s.startYAni(val,s.easeYComp,time);
		}
		private startYAni(val:number,compFunc:(tween:GYTween)=>void=null,time:number=1000):void
		{
			let s = this;
			var t:number = val - s.clipY;
			if(time <= 0 || time != time)return;
			if(t == 0)return;
			if(s._tweenY)
			{
				s._tweenY.clear();
				s._tweenY = null;
			}
			time *= s._scrollSpeedY;
			if(time == 0)return;			
			s._tweenY = GYTween.to(this,[TweenData.getInstance("clipY",val,NaN,GYTween.reduceEase)],time,0,s,compFunc,null,null,true,false);
		}
		private easeYComp(tar:any):void
		{
			let s = this;
			s._tweenY = null;
			var dis:number;
			let cpY:number = s.clipY;
			dis=s._limitYMax==s._limitYMax?s._limitYMax:s.contentHeight - s.baseHeight;
			if(dis < s._limitYMin)dis = s._limitYMin;
			if(s._easeGapY)
			{
				if(cpY < s._limitYMin && s._easeYFix != -cpY)
					s.startYAni(cpY < -s._easeYFix+s._limitYMin?-s._easeYFix+s._limitYMin:s._limitYMin);
				else if(cpY > dis && s._easeYFix + dis != cpY)
					s.startYAni((cpY > dis + s._easeYFix)?dis + s._easeYFix:dis);
			}
			else
			{
				if(cpY < s._limitYMin)
					s.clipY = s._limitYMin;
				else if(cpY > dis)
					s.clipY = dis;
			}
			s.dispatchEvent(new GYViewEvent(GYViewEvent.SCROLLEND_VERTICAL));
		}
		/**缓动到某X坐标*/
		public clipXEaseTo(val:number,time:number=1000):void
		{
			let s = this;
			s.startXAni(val,s.easeXComp, time);
		}
		private startXAni(val:number,compFunc:(tween:GYTween)=>void=null, time:number=1000):void
		{
			let s = this;
			var t:number = val - s.clipX;
			if(time <= 0 || time != time)return;
			if(t == 0)return;
			if(s._tweenX)
			{
				s._tweenX.clear();
				s._tweenX = null;
			}
			time *= s._scrollSpeedY;
			if(time == 0)return;		
			s._tweenX = GYTween.to(this,[TweenData.getInstance("clipX",val,NaN,GYTween.reduceEase)],time,0,s,compFunc,null,null,true,false);
		}
		private easeXComp(tar:any):void
		{
			let s = this;
			s._tweenX = null;
			var dis:number=s._limitXMax==s._limitXMax?s._limitXMax:s.contentWidth - s.baseWidth;
			let cpX:number = s.clipX;
			if(dis < s._limitXMin)dis =s._limitXMin;
			if(s._easeGapX)
			{
				if(cpX < s._limitXMin && s._easeXFix != -cpX)
					s.startXAni(cpX < -s._easeXFix+s._limitXMin?-s._easeXFix+s._limitXMin:s._limitXMin);
				else if(cpX > dis && s._easeXFix + dis != cpX)
					s.startXAni((cpX > dis + s._easeXFix)?dis + s._easeXFix:dis);
			}
			else
			{
				if(cpX < s._limitXMin)
					s.clipX = s._limitXMin;
				else if(cpX > dis)
					s.clipX = dis;
			}
			s.dispatchEvent(new GYViewEvent(GYViewEvent.SCROLLEND_HORIZONAL));
		}
		/**弹性恢复停止值(上下占位像素)，大于等于0*/
		public get easeYFix():number
		{let s = this;
			return s._easeYFix;
		}
		public set easeYFix(val:number)
		{let s = this;
			s._easeYFix = val;
			if(!s.dragLock)
			{
				var dis=s._limitYMax==s._limitYMax?s._limitYMax:s.contentHeight - s.baseHeight;
				if(dis < s._limitYMin)dis =s._limitYMin;
				let eY:number;
				eY = s.easeOutY;
				if(eY < -s._easeYFix+s._limitYMin)
					s.startYAni(-s._easeYFix+s._limitYMin);
				else if(eY > s._easeYFix)
					s.startYAni(s._easeYFix + dis);
			}
				
		}
		/**弹性恢复停止值(左右占位像素)，大于等于0*/
		public get easeXFix():number
		{let s = this;
			return s._easeXFix;
		}
		public set easeXFix(val:number)
		{let s = this;
			s._easeXFix = val;
			if(!s.dragLock)
			{
				var dis=s._limitXMax==s._limitXMax?s._limitXMax:s.contentWidth - s.baseWidth;
				if(dis < s._limitXMin)dis =s._limitXMin;
				let eX:number;
				eX = s.easeOutX;
				if(eX < -s._easeXFix+s._limitXMin)
					s.startXAni(-s._easeXFix+s._limitXMin);
				else if(eX > s._easeXFix)
					s.startXAni(s._easeXFix + dis);
			}
		}
		/**超出闪现边界范围值，上边界为负数，下边界为正数*/
		public get easeOutY():number
		{let s = this;
			let dis:number=s._limitYMax==s._limitYMax?s._limitYMax:s.contentHeight - s.baseHeight;
			let cY:number = s.clipY;
			if(dis < s._limitYMin)dis =s._limitYMin;
			return cY < s._limitYMin?(cY-s._limitYMin):(cY > dis?cY - dis:s._limitYMin);
		}
		/**超出左右边界范围值，左边界为负数，右边界为正数*/
		public get easeOutX():number
		{let s = this;
			let dis:number=s._limitXMax==s._limitXMax?s._limitXMax:s.contentWidth - s.baseWidth;
			let cX:number = s.clipX;
			if(dis < s._limitXMin)dis =s._limitXMin;
			return cX < s._limitXMin?(cX - s._limitXMin):(cX > dis?cX - dis:s._limitXMin);
		}
		public set easeGapY(val:boolean)
		{
			let s = this;
			s._easeGapY = val;
		}
		public set easeGapX(val:boolean)
		{
			let s = this;
			s._easeGapX = val;
		}
		/**是否超出底边界弹性恢复*/
		public get easeGapY():boolean
		{
			let s = this;
			return s._easeGapY;
		}
		/**是否超出底边界弹性恢复*/
		public get easeGapX():boolean
		{
			let s = this;
			return s._easeGapX;
		}
		
		protected _oldMouseChildren:boolean;
		protected _dragLock:boolean=false;
		/**拖动group时锁上内容不响应鼠标事件*/
		protected set dragLock(val:boolean)
		{
			let s = this;
			if(s._dragLock == val)
				return;
			s._dragLock = val;
			if(val)
			{
				s._oldMouseChildren = s.touchChildren;
				s.touchChildren = false;
				// var len:number;
				// len = s.numElement;
				// while(--len>-1)
				// {
				// 	if(CommonUtil.GYIs(s.elementVec[len], GYLite.GYSprite))
				// 		(s.elementVec[len] as GYSprite).touchChildren = (s.elementVec[len] as GYSprite).touchEnabled = false;
				// }
			}
			else
			{
				s.touchChildren = s._oldMouseChildren;
				// len = s.numElement;
				// while(--len>-1)
				// {
				// 	if(CommonUtil.GYIs(s.elementVec[len], GYLite.GYSprite))
				// 		(s.elementVec[len] as GYSprite).touchChildren = (s.elementVec[len] as GYSprite).touchEnabled = s._oldMouseChildren;
				// }
			}
		}
		protected get dragLock():boolean
		{
			let s = this;
			return s._dragLock;
		}	
		
		/**css层级显示*/
		public invalidZIndex():void
		{let s =this;
			if(!s.clipAndEnableScrolling)return;
			if(!s._outSideOptimize)return;
			super.invalidZIndex();			
		}

		public validZIndex():void
		{let s = this;
			let i:number,j:number,len:number;
			let disObj:IGYDisplay;
			let vec:Array<IGYDisplay>;			
			s._endPointer.y = s._endPointer.x = 0;
			vec = s._innerSprite.getElementList();
			vec.length = 0;			
			len = s._indexArray.length;
			for(i=0,j=0;i<len;++i)
			{
				disObj = s._indexArray[i];
				if(!disObj.offLayout)
					s.updateContentSize(disObj);
				if(disObj.parent != s._innerSprite && disObj.parent != s._outSideSp)
				{
					s._indexArray.splice(len,1);
					continue;
				}
				if(s._innerSprite == disObj.parent)
				{
					vec[j] = disObj;
					s._innerSprite.addChild(<egret.DisplayObject><any>disObj);
					++j;
				}				
			}
			if(s._scroller)
				s._scroller.checkBar();
		}
		
		protected updateContentSize(child:IGYDisplay):void
		{let s = this;
			let tx:number,ty:number,w:number,h:number;
			tx = child.x;
			ty = child.y;
			w = child.width * child.scaleX;
			h = child.height * child.scaleY;
			if(tx + w > s._endPointer.x)s._endPointer.x = tx + w - 1 + s._scrollPadLeft + s._scrollPadRight;
			if(ty + h > s._endPointer.y)s._endPointer.y = ty + h - 1 + s._scrollPadTop + s._scrollPadBottom;
		}

		public set outSideOptimize(val:boolean)
		{let s = this;
			s._outSideOptimize = val;
			s.checkOutSize();
		}

		public get outSideOptimize():boolean
		{
			return this._outSideOptimize;
		}
		/**检测屏内外元素
		 * @param checkChild 需要进行检测的显示对象
		 * @param updateZIndex 是否更新层级
		*/
		public checkOutSize(checkChild:IGYDisplay= null,updateZIndex:boolean=false):void
		{let s = this;
			let len:number,len2:number;
			let child:IGYDisplay;
			let inViewFlag:boolean;
			if(!s._outSideOptimize)return;
			if(!s._clipAndEnableScrolling)return;
			s._outSideSp.scrollRect.x = s._clipRect.x;
			s._outSideSp.scrollRect.y = s._clipRect.y;
			s._outSideSp.scrollRect.width = s._clipRect.width;
			s._outSideSp.scrollRect.height = s._clipRect.height;	
			if(checkChild)
			{			
				let inParentView:boolean = checkChild.inParentView(-s._scrollPadLeft,s._scrollPadRight,-s._scrollPadTop,s._scrollPadBottom);
				if(checkChild != s._endPointer && !checkChild.offLayout && checkChild.parent!=s._outSideSp)	
				{
					if(s._outSideOptimize && !inParentView)
					{										
						s._outSideSp.addElement(checkChild);					
					}
				}
				if(checkChild.parent!=s._innerSprite)
				{
					if(!s._outSideOptimize || inParentView)
					{											
						s._innerSprite.addElement(checkChild);
						inViewFlag = true;
					}						
				}
			}
			else
			{
				len = s._innerSprite.numElement;
				len2 = s._outSideSp.numElement;
				while(--len>-1)
				{
					child = s._innerSprite.getElementAt(len);
					if(child == s._endPointer)continue;			
					if(child.offLayout)continue;
					if(s._outSideOptimize && !child.inParentView(-s._scrollPadLeft,s._scrollPadRight,-s._scrollPadTop,s._scrollPadBottom))
					{							
						if(child.parent!=s._outSideSp)
						{						
							s._outSideSp.addElement(child);
						}						
					}
				}			
				while(--len2>-1)
				{
					child = s._outSideSp.getElementAt(len2);				
					if(!s._outSideOptimize || child.inParentView(-s._scrollPadLeft,s._scrollPadRight,-s._scrollPadTop,s._scrollPadBottom))
					{
						if(child.parent!=s._innerSprite)
						{						
							s._innerSprite.addElement(child);
							inViewFlag = true;
						}						
					}				
				}
			}					
			
			//若进出屏内容器改变
			//则要顺便刷新层级，此处为clip刷新触发，clip刷新优先级比ZIndex高，所以此处刷新Zindex能立即生效
			//若存在滚动条，滚动条也刷新一下
			if(inViewFlag || updateZIndex)
			{
				s.invalidZIndex();
				s.invalidDisplay();				
			}				
		}
		/**覆盖getAllBounds,以便得到真实内容的宽高*/
		public getAllBounds(t:IGYDisplay):egret.Rectangle
		{
			let s = this;
			s._boundRect.x = s._boundRect.y = 0;
			s._boundRect.width = s._endPointer.x;
			s._boundRect.height = s._endPointer.y;
			s.$contentWidth = s._boundRect.x + s._boundRect.width;
			s.$contentHeight = s._boundRect.y + s._boundRect.height;
			return s._boundRect;
		}
		public get scrollPadLeft():number
		{
			return this._scrollPadLeft;
		}
		public set scrollPadLeft(val:number)
		{let s = this;
			if(s._scrollPadLeft == val)return;
			s._scrollPadLeft = val;
			s._innerSprite.x = s._scrollPadLeft;
		}
		public get scrollPadRight():number
		{
			return this._scrollPadRight;
		}
		public set scrollPadRight(val:number)
		{let s = this;
			if(s._scrollPadRight == val)return;
			s._scrollPadRight = val;			
		}
		public get scrollPadTop():number
		{
			return this._scrollPadTop;
		}
		public set scrollPadTop(val:number)
		{let s = this;
			if(s._scrollPadTop == val)return;
			s._scrollPadTop = val;
			s._innerSprite.y = s._scrollPadTop;
		}
		public get scrollPadBottom():number
		{
			return this._scrollPadBottom;
		}
		public set scrollPadBottom(val:number)
		{let s = this;
			if(s._scrollPadBottom == val)return;
			s._scrollPadBottom = val;			
		}		

		public set limitXMin(val:number)
		{let s = this;
			s._limitXMin = val;
			if(s._scroller && s._scroller.horizonPolicy != 2)
				s._scroller.scrollBarH.limitMin = s._limitXMin;
		}
		public get limitXMin():number
		{
			return this._limitXMin;
		}
		/**限制滚动x方向最大值，默认NaN，不限制*/
		public set limitXMax(val:number)
		{let s = this;
			s._limitXMax = val;
			if(s._scroller && s._scroller.horizonPolicy != 2)
				s._scroller.scrollBarH.limitMax = s._limitXMax;
		}
		/**限制滚动x方向最小值，默认NaN，不限制*/
		public get limitXMax():number
		{
			return this._limitXMax;
		}

		public set limitYMin(val:number)
		{let s = this;
			s._limitYMin = val;
			if(s._scroller && s._scroller.verticalPolicy != 2)
				s._scroller.scrollBarV.limitMin = s._limitYMin;
		}
		/**限制滚动y方向最小值，默认NaN，不限制*/
		public get limitYMin():number
		{
			return this._limitYMin;
		}
		public set limitYMax(val:number)
		{let s = this;
			s._limitYMax = val;
			if(s._scroller && s._scroller.verticalPolicy != 2)
				s._scroller.scrollBarV.limitMax = s._limitYMax;
		}
		/**限制滚动y方向最大值，默认NaN，不限制*/
		public get limitYMax():number
		{
			return this._limitYMax;
		}
		/**停止拖动响应*/
		public stopDrag():void
		{
			let s= this;
			s.easeSpeedX = s.easeSpeedY =0;
			s.upGroup();
		}
		/**是否拖拽中*/
		public get isDragging():boolean
		{
			return this._isDragging;
		}				
		
		
		/**产生缓动的速度*/public static default_easeValue:number = 5;
		// /**回弹系数*/public static default_easeBackValue:number = 200;
		/**拖动敏感度*/public static default_dragValue:number = 2;
		/**加速度系数1/2a*/public static default_easeSpeedValue = 0.5;
		/**边界拖拽系数*/public static default_dragEaseValue:number = 20;
		/**拖拽步长最大值*/public static default_dragEaseMax:number = 20;
		/**缓动越界最大值*/public static default_easeMoveMax:number = 20;
		/**触发缓动的时间阈值*/public static default_easeTriggerTime:number = 200;
		/**弹性恢复时间*/public static default_easeTime:number = 500;
	}
	export class InnerSprite extends GYUIComponent
	{
		private _virtualParent:GYLite.GYGroup;
		public constructor(pr:GYLite.GYGroup)
		{
			super();
			this._virtualParent = pr;
		}
		public get parent():GYLite.GYGroup
		{
			return this._virtualParent;
		}
	}
}